<?php
	
	/* Structure de type arbre classique : un noeud est un élément ayant
	 * un array de fils. On appelle d'abord le constructeur, puis la méthode
	 * fetchResultSet et enfin createTreeFromResultSet.
	 */
	
	error_reporting(E_ALL);
	ini_set('display_errors', true);
	
	include_once "inc/defines.php";
	
	$liID = 0; // Variable globale pour les ID des <li> de la methode treeToHtml
	
	class treenode {
		private $childNodes = array();
		private $id;
		private $type;
		private $specialType;
		private $content;
		private $sqlQuery;
		private $resultSet;
		
		public function __construct($content, $id, $type) {
			$this->type = $type;
			$this->specialType = null;
			$this->id = $id;
			$this->content = $content;
		}
		
		public function addChildNode($addedNode) {
			array_push($this->childNodes, $addedNode);
		}
		
		private function getID() {
			return $this->id;
		}
		
		private function getType() {
			return $this->type;
		}
		
		public function getSpecialType() {
			return $this->specialType;
		}
		
		public function setSpecialType($specialType) {
			$this->specialType = $specialType;
		}
		
		public function getChildNodes() {
			return $this->childNodes;
		}
		
		private function getContent() {
			return $this->content;
		}
		
		private function nodeCount() {
			return count($this->childNodes);
		}
		
		public function fetchResultSet($sqlQuery) {
			$this->sqlQuery = $sqlQuery;
			$db = new PDO(SERVER.":host=".HOST.";dbname=".BASE, USER, PASS);
			$st = $db->prepare($sqlQuery);
			$st->execute();
			$resultSet = array();
			while($ligne = $st->fetch(PDO::FETCH_NUM)) //FETCH_NUM permet d'indexer uniquement sur 0, 1, 2... et non sur 0, 1, 2... ET 'id_form', 'nom_form' etc
				array_push($resultSet, $ligne);
			$db = null;
			$this->resultSet = $resultSet;
		}
		
		public function createTreeFromResultSet() {
			if($this->resultSet != NULL)
				treenode::fillTree($this, $this->resultSet, $this->depth($this->resultSet), 0, true);
		}
		
		public static function depth($resultSet) {
			$maxLevel = count($resultSet[0]);
			for($i = 0; $i < count($resultSet); $i++)
				if($maxLevel < count($resultSet[$i]))
					$maxLevel = count($resultSet[$i]);
			return $maxLevel;
		}
		
		private static function fillTree($rootNode, $resultSet, $depth, $level, $firstPass) {
			if($level < $depth) {
				$IDArray = array();
				for($i = 0; $i < count($resultSet); $i++) {
					if($firstPass || $resultSet[$i][$level - 2] == $rootNode->getID()) {
						if(isset($resultSet[$i][$level]) && !in_array($resultSet[$i][$level], $IDArray)) {
							array_push($IDArray, $resultSet[$i][$level]);
							$rootNode->addChildNode(new treenode($resultSet[$i][$level + 1], $resultSet[$i][$level], $level / 2));
						}
					}
				}
				foreach($rootNode->childNodes as $node)
					treenode::fillTree($node, $resultSet, $depth, $level + 2, false);
			}
		}
		
		public function refresh() {
			$this->resultSet = NULL; //effacer le resultat de la requete SQL
			$this->fetchResultSet($this->sqlQuery);
			$this->childNodes = array(); //effacer les fils actuels
			$this->createTreeFromResultSet();
		}
		
		public static function treeToHtml($t, $treeType, $depth) {
			global $liID;
			$class = "";
			if(isset($_GET["liid"]) && $_GET["liid"] == $liID)
				$class = " class=\"jstree-clicked\" ";
			if($t->getID() == NULL)
				echo "<ul><li id=\"li".$liID."\"><a $class href=\"?liid=".$liID."&amp;treetype=".$treeType."\">".$t->getContent()."</a>";
			else {
				if($t->getType() < $depth) {
					echo "<ul><li id=\"li".$liID."\"><a $class href=\"?liid=".$liID."&amp;treetype=".$treeType;
					if($t->getSpecialType() != null)
						echo "&amp;special=".$t->getSpecialType();
					echo "&amp;nodetype=".$t->getType()."&amp;nodename=".str_replace(" ", "%20", $t->getContent())."&amp;id=".$t->getID()."\">".$t->getContent()."</a>";
				}
			}
			$liID++;
			foreach($t->childNodes as $node) {
					treenode::treeToHtml($node, $treeType, $depth);
			}
			if($t->getType() < $depth)
				echo "</li></ul>";
		}
		
		public function hasNoChilds() {
			$foo = $this->getChildNodes();
			return empty($foo); //on ne peut pas faire return empty($this->getChildNodes()); directement, voir http://stackoverflow.com/a/1075559
		}
	}
	
?>
